﻿#include "_AudioPlayer.h"
/*
	Copyright (C) 2019 Zongming Liu <1849059316@qq.com>

	This program is free software; you can redistribute it and/or modify
	it under the terms of the GNU General Public License as published by
	the Free Software Foundation; either version 2 of the License, or
	(at your option) any later version.
	
	This program is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
	GNU General Public License for more details.
	
	You should have received a copy of the GNU General Public License along
	with this program; if not, write to the Free Software Foundation, Inc.,
	51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/

#include "_AudioPlayer.h"

namespace SkyEngine2d
{	
	static HMODULE getModuleHandle()
	{
		static HMODULE instance = GetModuleHandle(nullptr);
		return instance;
	}
	
	static std::wstring CLASS_NAME = L"{70BCBF96-F99E-44E4-8AE6-B62B41F28EFF}";
	
	static LRESULT WINAPI proc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam);
	
	AudioPlayer::~AudioPlayer()
	{
		this->unload();
		DestroyWindow(m_wnd);
	}
	
	bool AudioPlayer::load(const std::wstring & file_path)
	{
		if (file_path.empty())
		{
			return false;
		}
	
		m_audioName = file_path;
	
		if (m_isLoad)
		{
			this->unload();
		}
	
		MCI_OPEN_PARMS mciOpen = { 0 };
		MCIERROR mciError;
		mciOpen.lpstrDeviceType = (LPCTSTR)MCI_ALL_DEVICE_ID;
		mciOpen.lpstrElementName = file_path.c_str();
	
		mciError = mciSendCommand(0, MCI_OPEN, MCI_OPEN_ELEMENT, reinterpret_cast<DWORD_PTR>(&mciOpen));
		if (mciError)
		{
			return false;
		}
			
		m_dev = mciOpen.wDeviceID;
			
		m_isPlaying = false;
		
		m_isLoad = true;
	
		return true;
	}
	
	void AudioPlayer::unload()
	{
		if (m_isPlaying)
		{
			this->stop();
		}
		if (m_dev)
		{
			mciSendCommand(m_dev, MCI_CLOSE , 0, 0);
		}
		m_dev = 0;
		m_isPlaying = false;
		m_isLoad = false;
	}
	
	void AudioPlayer::play(bool is_loop)
	{
		if (!m_dev)
		{
			return;
		}
	
		MCI_PLAY_PARMS mciPlay = { 0 };
		mciPlay.dwCallback = reinterpret_cast<DWORD_PTR>(m_wnd);
		auto s_mciError = mciSendCommand(m_dev, MCI_PLAY, MCI_FROM | MCI_NOTIFY, reinterpret_cast<DWORD_PTR>(&mciPlay));
		if (s_mciError)
		{	
			return;
		}
	
		m_isPlaying = true;
		m_isLoop = is_loop;
	
		return;
	}
	
	void AudioPlayer::stop()
	{
		if (m_dev)
		{
			mciSendCommand(m_dev, MCI_STOP, 0, 0);
		}
		m_isPlaying = false;
		m_isLoop = false;
	}
	
	
	
	void AudioPlayer::pause()
	{
		if (m_dev)
		{
			mciSendCommand(m_dev, MCI_PAUSE, 0, 0);
		}
		m_isPlaying = false;
	}
	
	void AudioPlayer::resume()
	{
		if (m_dev)
		{
			mciSendCommand(m_dev, MCI_RESUME,0,0);
		}
		m_isPlaying = true;
	}
	
	
	bool AudioPlayer::isPlaying()
	{
		return m_isPlaying;
	}
	
	bool AudioPlayer::isLoop()
	{
		return m_isLoop;
	}
	
	MCIDEVICEID AudioPlayer::getMciDev()
	{
		return m_dev;
	}
	
	HWND AudioPlayer::getWnd()
	{
		return m_wnd;
	}
	
	const std::wstring AudioPlayer::getAudioName()
	{
		return m_audioName;
	}
	
	AudioPlayer::AudioPlayer()
		:m_isLoop(false)
		,m_isPlaying(false)
		,m_isLoad(false)
		,m_wnd(0)
		,m_dev(0)
	{
		WNDCLASS  wc;
		wc.style = 0;
		wc.lpfnWndProc = proc;
		wc.cbClsExtra = 0;   
		wc.cbWndExtra = 0;  
		wc.hInstance = getModuleHandle();   
		wc.hIcon = 0;                             
		wc.hCursor = LoadCursor(NULL, IDC_ARROW);  
		wc.hbrBackground = NULL;                        
		wc.lpszMenuName = NULL;                        
		wc.lpszClassName = CLASS_NAME.c_str();                
	
		if (!RegisterClass(&wc) && 1410 != GetLastError())
		{
			return;
		}
		
	
		m_wnd = CreateWindowEx(
			WS_EX_APPWINDOW,                                  
			CLASS_NAME.c_str(),
			NULL,                                      
			WS_POPUPWINDOW,
			0, 0,                                        
			0,                                                 
			0,                                                    
			NULL,                                               
			NULL,                                             
			getModuleHandle(),                               
			NULL);
	
		if (m_wnd)
		{
			SetWindowLongPtr(m_wnd, GWLP_USERDATA, (LONG_PTR)this);
		}
	}
	
	
	
	//处理 MCI 的消息
	LRESULT WINAPI proc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
	{
		if (MM_MCINOTIFY == Msg && MCI_NOTIFY_SUCCESSFUL == wParam)
		{
			AudioPlayer * p = (AudioPlayer*)GetWindowLongPtr(hWnd, GWLP_USERDATA);
			if (p)
			{
				if (p->isLoop())
				{
					mciSendCommand(lParam, MCI_SEEK, MCI_SEEK_TO_START, 0);
					MCI_PLAY_PARMS mciPlay = { 0 };
					mciPlay.dwCallback = reinterpret_cast<DWORD_PTR>(hWnd);
					mciSendCommand(lParam, MCI_PLAY, MCI_NOTIFY, reinterpret_cast<DWORD_PTR>(&mciPlay));
				}
				else
				{
					p->m_isPlaying = false;
				}
			}
			return 0;
		}
	
		return DefWindowProc(hWnd, Msg, wParam, lParam);
	}
}
